"""
图片自动描边
输入一张图片，返回一张图片的差值，根据相邻像素的颜色差异来涂色
2020年5月2日
by littlefean
"""
from PIL import Image
from math import sqrt
from time import time


def distance(color1, color2):
    """
    输入两个颜色数据，返回它们的差值
    此差值是rgb构成的三维空间中的欧氏距离
    :param color1: 颜色1 如：(20, 34, 67)
    :param color2: 颜色2
    :return: 差值
    """
    d = sqrt((color1[0] - color2[0]) ** 2 + (color1[1] - color2[1]) ** 2 + (color1[2] - color2[2]) ** 2)
    return d

def right(im, d):
    """
    传入一个图片路径和颜色差值参数d，在此py文件目录下保存一张图片
    此函数将传入图片的每个像素对比其右边一个像素，
    颜色差异距离超过d的像素位置对应输出图片中的白色，其余是黑色
    :param im: 图片路径
    :param d: 差值
    :return:
    """
    putColor = (255, 255, 255)  # 差异过大时候涂的白色
    img = Image.open(im)
    w1 = img.width  # 图片的宽
    h1 = img.height  # 图片的高
    im3 = Image.new('RGB', (w1, h1), 'black')
    for y in range(h1):
        for x in range(w1):
            src_str_list = img.load()  # 当前图片的所有像素信息列表
            if x < (w1 - 2):
                if distance(src_str_list[x, y], src_str_list[x + 1, y]) >= d:
                    im3.putpixel((x, y), putColor)
            else:
                im3.putpixel((x, y), (0, 0, 0))
    im3.save(f'DSr_{d}_{time()}.png')


def right_down(im, d, black=False):
    """
    同right函数，对比差异过大条件为右侧一个像素或下方一个像素与原位置颜色差值超过d
    参考 right函数
    black可选参数：若为True则输出黑底白边的图片，默认白底黑边
    """
    img = Image.open(im)
    w1, h1 = img.width, img.height  # 图片的宽高
    if black:
        putColor = (255, 255, 255)  # 差异过大时候涂的白色
        im3 = Image.new('RGB', (w1, h1), 'black')
    else:
        putColor = (0, 0, 0)
        im3 = Image.new('RGB', (w1, h1), (255, 255, 255))
    for y in range(h1):
        for x in range(w1):
            src_str_list = img.load()  # 当前图片的所有像素信息列表
            if (x < (w1 - 2)) and (y < (h1 - 2)):
                if (distance(src_str_list[x, y], src_str_list[x + 1, y]) >= d) \
                        or (distance(src_str_list[x, y], src_str_list[x, y + 1]) >= d):
                    im3.putpixel((x, y), putColor)
            else:
                im3.putpixel((x, y), (0, 0, 0))
    im3.save(f'DSrd_{d}_{time()}.png')


def right_down_stage(im, d):
    """
    参考right_down函数
    每个像素对比自己右边和下面的一个像素并输出一张图片，
    这张图片上越白的地方表示差异程度越大的地方
    """
    img = Image.open(im)
    w1 = img.width  # 图片的宽
    h1 = img.height  # 图片的高
    im3 = Image.new('RGB', (w1, h1), 'black')
    for y in range(h1):
        for x in range(w1):
            if (x < (w1 - 2)) and (y < (h1 - 2)):
                src_str_list = img.load()  # 当前图片的所有像素信息列表
                d1 = distance(src_str_list[x, y], src_str_list[x + 1, y])
                d2 = distance(src_str_list[x, y], src_str_list[x, y + 1])
                if d1 > d2:
                    d = d1
                else:
                    d = d2
                pc = int(255 * d / sqrt(255 ** 2 + 255 ** 2 + 255 ** 2))
                im3.putpixel((x, y), (pc, pc, pc))
            else:
                im3.putpixel((x, y), (0, 0, 0))
    im3.save(f'DSrds_{d}_{time()}.png')


if __name__ == '__main__':
    right_down('05.jpg', 25, black=True)